home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Libris Britannia 4
/
science library(b).zip
/
science library(b)
/
DJGPP
/
DJLSR111.ZIP
/
lib
/
mcount.c
< prev
Wrap
C/C++ Source or Header
|
1992-07-06
|
3KB
|
142 lines
#include <fcntl.h>
/* header of a GPROF type file
*/
typedef struct {
long low;
long high;
long nbytes;
} header;
/* entry of a GPROF type file
*/
typedef struct {
unsigned long from;
unsigned long to;
unsigned long count;
} MTABE;
/* internal form - sizeof(MTAB) is 4096 for efficiency
*/
typedef struct MTAB {
MTABE calls[341];
struct MTAB *prev;
} MTAB;
static header h;
short *histogram asm("mcount_histogram");
short mcount_skip asm("mcount_skip");
static int histlen;
static MTAB *mtab=0;
/* called by functions. Use the pointer it provides to cache
** the last used MTABE, so that repeated calls to/from the same
** pair works quickly - no lookup.
*/
void mcount(_to)
{
MTAB *m;
int i;
int to;
int ebp;
int from;
int mtabi;
MTABE **cache;
mcount_skip = 1;
asm("movl %%edx,%0" : "=g" (cache)); /* obtain the cached pointer */
to = *((&_to)-1) - 12;
ebp = *((&_to)-2); /* glean the caller's return address from the stack */
from = ((int *)ebp)[1];
if (*cache && ((*cache)->from == from) && ((*cache)->to == to))
{
/* cache paid off - works quickly */
(*cache)->count++;
mcount_skip = 0;
return;
}
/* no cache hit - search all mtab tables for a match, or an empty slot */
mtabi = -1;
for (m=mtab; m; m=m->prev)
{
for (i=0; i<341; i++)
{
if (m->calls[i].from == 0)
{
/* empty slot - end of table */
mtabi = i;
break;
}
if ((m->calls[i].from == from) &&
(m->calls[i].to == to))
{
/* found a match - bump count and return */
m->calls[i].count ++;
*cache = m->calls + i;
mcount_skip = 0;
return;
}
}
}
if (mtabi != -1)
{
/* found an empty - fill it in */
mtab->calls[mtabi].from = from;
mtab->calls[mtabi].to = to;
mtab->calls[mtabi].count = 1;
*cache = mtab->calls + mtabi;
mcount_skip = 0;
return;
}
/* lob off another page of memory and initialize the new table */
m = (MTAB *)sbrk(sizeof(MTAB));
memset(m, 0, sizeof(MTAB));
m->prev = mtab;
mtab = m;
m->calls[0].from = from;
m->calls[0].to = to;
m->calls[0].count = 1;
*cache = m->calls;
mcount_skip = 0;
}
extern int etext;
extern void mcount_isr_init() asm("mcount_isr_init");
extern void mcount_init() asm("mcount_init");
void mcount_init()
{
/* this is called by gcrt0.s, before the program starts */
int hs;
h.low = 0x1020;
h.high = (int)&etext;
histlen = (h.high-h.low)/4*sizeof(short);
h.nbytes = sizeof(header) + histlen;
histogram = (short *)sbrk(histlen);
memset(histogram, 0, histlen);
/* here, do whatever it takes to initialize the timer interrupt */
mcount_isr_init();
}
extern void mcount_write() asm("mcount_write");
void mcount_write()
{
/* this is called by gcrt0.s, after the program exits. */
MTAB *m;
int i, f;
f = open("gmon.out", O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0666);
write(f, &h, sizeof(header));
write(f, histogram, histlen);
for (m=mtab; m; m=m->prev)
{
for (i=0; i<341; i++)
if (m->calls[i].from == 0)
break;
write(f, m->calls, i*12);
}
close(f);
}